package cn.cyh.queue_service.mq.consumer;

import cn.cyh.queue_service.config.RabbitMQConfig;
import cn.cyh.queue_service.model.dto.TakeNumberRequest;
import cn.cyh.queue_service.model.dto.TakeNumberResponse;
import cn.cyh.queue_service.mq.event.TakeNumberEvent;
import cn.cyh.queue_service.service.CacheService;
import cn.cyh.queue_service.service.QueueService;
import cn.cyh.queue_service.service.StatisticsService;
import cn.cyh.queue_service.websocket.CurrentQueues;
import cn.cyh.queue_service.websocket.CurrentScreens;
import cn.cyh.queue_service.websocket.SocketMsg;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;

/**
 * 取号事件消费者
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class TakeNumberEventConsumer {

    @Resource
    private QueueService queueService;
    @Resource
    private StatisticsService statisticsService;
    @Resource
    private CacheService cacheService;
    @Resource
    private ObjectMapper objectMapper;
    
    /**
     * 处理取号事件
     *
     * @param message 消息
     * @param channel 通道
     */
    @RabbitListener(queues = RabbitMQConfig.TAKE_NUMBER)
    public void handleTakeNumberEvent(Message message, Channel channel) throws IOException {
        try {
            // 获取消息内容
            String content = new String(message.getBody());
            TakeNumberEvent event = objectMapper.readValue(content, TakeNumberEvent.class);
            if (!RabbitMQConfig.TAKE_NUMBER.equals(event.getEventType())) {
                return;
            }
            log.info("收到取号事件: {}", event.getTicketNumber());

            // 获取最新票号
            TakeNumberRequest request = new TakeNumberRequest();
            request.setServiceTypeId(event.getServiceTypeId());
            TakeNumberResponse takeNumberResponse = queueService.takeNumber(request);
            // 通知用户取号成功
            WebSocketSession session = CurrentQueues.sessionMap.get(event.getSessionId());
            SocketMsg msg = new SocketMsg();
            msg.setType("getNumber");
            msg.setData(takeNumberResponse);
            broadcastMessage(session, JSONUtil.toJsonStr(msg));

            // 更新统计数据 - 等待人数
            statisticsService.updateWaitingCount(event.getServiceTypeId());
            // 更新缓存
            String cacheKey = "queue:waiting:" + event.getServiceTypeId();
            cacheService.rightPush(cacheKey, event.getTicketNumber());
            // 刷新数据
            CurrentQueues.sendRefreshData();
            CurrentScreens.sendRefreshData();
            // 确认消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            log.error("处理取号事件失败", e);
        }
    }

    private void broadcastMessage(WebSocketSession session, String message) {
        try {
            if (session.isOpen()) {
                session.sendMessage(new TextMessage(message));
            }
        } catch (IOException e) {
            log.error("发送消息时发生错误: {}", e.getMessage(), e);
            throw new RuntimeException(e.getMessage());
        }
    }
} 